#include <iostream>
#include <iomanip>
#include <limits>
#include <typeinfo>
using namespace std;
const int type_len = 20;
const int length = 25;

struct Polymorph
{
    virtual ~Polymorph(){}
};
    
template <typename T >
struct Type
{
    static  void print_min_max(){
        cout<<left<<setw(type_len)<< typeid(T).name() <<right<<setw(4)<<sizeof(T)
            << setw(length) << numeric_limits<T >::max()
            << setw(length) <<  numeric_limits<T >::min() <<endl;
    }    
};
enum Bit{Zero,One};
enum Intensity{black = 0,brightest = 1000};

    
    
int main()
{
    cout<< left << setw(type_len) << "Type "    << right << setw(4) << "Size"
        << right << setw(length) << "Max" << setw(length) << "Min" << endl<<endl;
    
    //char type
    Type<char>::print_min_max();
    Type<wchar_t>::print_min_max();
    Type<unsigned char>::print_min_max();
    Type<signed char>::print_min_max();
    
    //int type
    Type<int>::print_min_max ();
    Type<short int>::print_min_max ();
    Type<long int> ::print_min_max ();
    Type<signed int>::print_min_max();
    Type<signed long long>::print_min_max();
    Type<unsigned long long>::print_min_max();
    //float type
    Type<float>::print_min_max ();
    Type<double>::print_min_max ();
    Type<long double>::print_min_max ();
    Type<unsigned int>::print_min_max();
    //point type
    Type<int*>::print_min_max();
    Type<int(*)()>::print_min_max();//function pointer
    Type<void (Polymorph::*)()>::print_min_max();//member function pointer
    Type<void*>::print_min_max();

    //eunum type    
    Type<Bit>::print_min_max();
    Type<Intensity>::print_min_max();


    cout << endl;
    cout << "char is signed = " << numeric_limits<char>::is_signed << endl;
    

    return 0;
}
